﻿//本示例只是作为ws的功能演示,有很多地方是省略了且是可优化的,请勿直接照搬至生产环境

我的主窗口类  我的主窗口

#宏定义 菜单操作类型_断开连接 10001

函数 整型 WINAPI 操作列表菜单事件(整型 nID, 逻辑型* pBool)
	返回 我的主窗口.外部接口_断开连接(nID,pBool)

类 我的主窗口类
	[绑定信息] //IDE生成的UI绑定信息(UI变量,事件), 支持手动修改, 可收缩隐藏
		[窗口事件]
			[WM_CLOSE, 事件_关闭, 0]
		[按钮类, _按钮_开启服务器, "按钮_开启服务器"]
			[XE_BNCLICK, 事件_按钮_开启服务器_点击, 0]
		[按钮类, _按钮_关闭服务器, "按钮_关闭服务器"]
			[XE_BNCLICK, 事件_按钮_关闭服务器_点击, 0]
		[按钮类, _控制台_发送消息, "控制台_发送消息"]
			[XE_BNCLICK, 事件_控制台_发送消息_点击, 0]
		[编辑框类, _控制台_消息框, "_控制台_消息框"]
		[编辑框类, _IP框, "IP框"]
		[编辑框类, _端口框, "端口框"]
		[编辑框类, _日志框, "日志框"]
		[列表类,_连接列表,"连接列表"]
			[XE_RBUTTONUP, 事件_连接列表_鼠标右键弹起, 0]
	菜单类 操作列表菜单
	WS服务器 WsCore
	窗口句柄  _句柄
	逻辑型c 服务器开启状态=假
	//窗口类初始化, 自动处理关联的布局文件及绑定变量和注册事件
	函数 整型 运行(文本型 窗口布局文件 = "main.xml", 炫彩句柄 父句柄 = 0)
		WS_注册初始化()
		_连接列表.列表头创建数据适配器()
		_连接列表.创建数据适配器()
		_连接列表.添加列文本(100, "name1", "连接标志")
		_连接列表.添加列文本(120, "name2", "IP")
		窗口_注册事件C(_句柄,XWM_MENU_SELECT, 操作列表菜单事件)
		//元素_重绘(_连接列表.句柄, 真)
		窗口_显示(_句柄, TRUE)
		返回 0
	
	函数 输出日志(常量 单字符型* log)
		_日志框.添加文本(A2W(log))
		_日志框.添加文本("\n")
		元素_重绘(_日志框._句柄, 真)
	////-----------------------
	函数 整型  事件_关闭(逻辑型* 是否拦截)
		WsCore.停止()
		返回 0
	函数 整型  事件_按钮_开启服务器_点击(逻辑型* 是否拦截)
		如果 服务器开启状态
			返回 0
		服务器开启状态 = 真
		更新按钮状态()
		WS_启动服务器()
		返回 0
	函数 整型  事件_按钮_关闭服务器_点击(逻辑型* 是否拦截)
		如果 !服务器开启状态
			返回 0
		服务器开启状态 = 假
		更新按钮状态()
		WS_关闭服务器()
		返回 0
	函数 整型  事件_控制台_发送消息_点击(逻辑型* 是否拦截)
		cJSON类 json
		json.置文本(A"type", A"msg")
		json.置文本(A"name", A"服务器公告")
		json.置文本(A"msg", W2A(_控制台_消息框.取文本_临时()))
		_控制台_消息框.置文本("")
		元素_重绘(_控制台_消息框._句柄)
		WS_批量分发消息(json.取Json文本())
		返回 0
	函数 更新按钮状态()
		_IP框.启用(!服务器开启状态)
		_端口框.启用(! 服务器开启状态)
		_按钮_开启服务器.启用(! 服务器开启状态)
		_按钮_关闭服务器.启用(服务器开启状态)
		元素_重绘(_IP框._句柄, 真)
		元素_重绘(_端口框._句柄,真)
		元素_重绘(_按钮_开启服务器._句柄,真)
		元素_重绘(_按钮_关闭服务器._句柄, 真)
	函数 整型  事件_连接列表_鼠标右键弹起(整型 nFlags, POINT* pPt, 逻辑型* 是否拦截)
		点结构 point = 鼠标_取位置()
		操作列表菜单.创建()
		操作列表菜单.添加项(菜单操作类型_断开连接,"断开连接")
		操作列表菜单.弹出(窗口_取HWND(_句柄),point.x,point.y)
		返回 0
	////-----------------------
	函数 WS_注册初始化()
		WsCore.回调事件_建立连接(WS_绑定回调(&我的主窗口类::WS_事件_建立连接,本类,WS_绑定回调_参数占位符_1))
		WsCore.回调事件_连接失败(WS_绑定回调(&我的主窗口类::WS_事件_连接失败,本类,WS_绑定回调_参数占位符_1))
		WsCore.回调事件_收到消息(WS_绑定回调(&我的主窗口类::WS_事件_收到消息,本类,WS_绑定回调_参数占位符_1,WS_绑定回调_参数占位符_2))
		WsCore.回调事件_关闭连接(WS_绑定回调(&我的主窗口类::WS_事件_关闭连接, 本类, WS_绑定回调_参数占位符_1))
		WsCore.回调事件_Ping(WS_绑定回调(&我的主窗口类::WS_事件_客户端Ping, 本类, WS_绑定回调_参数占位符_1, WS_绑定回调_参数占位符_2))
		WsCore.回调事件_Pong(WS_绑定回调(&我的主窗口类::WS_事件_客户端Ping, 本类, WS_绑定回调_参数占位符_1,WS_绑定回调_参数占位符_2))
	函数 逻辑型c WS_事件_客户端Ping(WS连接* 会话指针, 常量 单字符型* 交换信息)
		如果 ! 文本比较A(交换信息, A"connect")
			会话指针->Pong()
			返回 真
		返回 假
	函数 WS_事件_客户端Pong(WS连接* 会话指针, 常量 单字符型* 交换信息)
		单字符型 buff[256]={0}
		文本格式化A(buff,sizeof(buff),A"[Pong] 标志:%lld IP:%s Payload:%s",(长整型)(会话指针->取连接标志()),会话指针->取客户端IP().取地址(),交换信息)
		输出日志(buff)
	函数 WS_事件_建立连接(WS连接* 会话指针)
		会话指针->Ping()
		单字符型 buff[256]={0}
		文本格式化A(buff,sizeof(buff),A"[建立连接] 标志:%lld IP:%s URI:%s",(长整型)(会话指针->取连接标志()),会话指针->取客户端IP().取地址(),会话指针->取请求URI().取地址())
		输出日志(buff)
		WS_加入客户(会话指针)
	函数 WS_事件_连接失败(WS连接* 会话指针)
		如果 缓存池.空值() == 缓存池.查找(会话指针->取连接标志())
			返回
	函数 WS_事件_收到消息(WS连接* 会话指针, WS消息_服务器* 消息体)
		单文本型 请求文本 = 编码_Utf8转Gbk(消息体->取文本数据A())
		单字符型 buff[256]={0}
		文本格式化A(buff,sizeof(buff),A"[收到消息][%lld %s][IP:%s]%s",(长整型)会话指针->取连接标志(),会话指针->取请求URI().取地址(),会话指针->取客户端IP().取地址(),请求文本.取地址())
		输出日志(buff)
		连接信息缓存* 用户信息  = 取连接缓存(会话指针)
		如果 用户信息 == 空
			//不存在于连接列表内的标志是怎么回事呢(笑
			WS_断开连接(会话指针)
			返回
		如果 请求文本 != A""
			cJSON类 json
			json.解析(请求文本)
			消息事件_分发消息(会话指针, 用户信息, json)
			//如果 jsonReader.取错误() == A""
		如果 ! 用户信息->连接许可
			//你被Ban了(笑
			单字符型 buff[250] = {0}
			会话指针->发送文本A(A"Auth Error")
			文本格式化A(buff, sizeof(buff), A"[Auth][IP:%s 标志:%lld]未授权访问,强制断开连接.", 会话指针->取客户端IP().取地址(), (长整型)会话指针->取连接标志())
			输出日志(buff)
			WS_断开连接(会话指针)
			返回
		//文本格式化A(buff, sizeof(buff), A"[客户端消息][IP:%s]", 会话指针->取客户端IP().取地址())
		//WS_批量分发消息(buff, 会话指针)
	函数 WS_事件_关闭连接(WS连接* 会话指针)
		单字符型 buff[256]={0}
		文本格式化A(buff,sizeof(buff),A"[断开连接] 标志:%lld IP:%s",(长整型)会话指针->取连接标志(),会话指针->取客户端IP().取地址())
		输出日志(buff)
		迭代器 连接 = 缓存池.查找(会话指针->取连接标志())
		如果 连接 == 缓存池.空值()
			返回
		delete 连接.值
		整型 num = 搜索客户索引(&_连接列表, 会话指针)
		如果 num >- 1
			_连接列表.删除行(num)
		缓存池.删除(连接.键)
		元素_重绘(_连接列表._句柄, 真)
	////-----------------------
	函数 WS_启动服务器()
		单字符型 buff[256] = {0}
		单文本型 临时文本_IP = W2A(_IP框.取文本_临时())
		单文本型 临时文本_端口 = W2A(_端口框.取文本_临时())
		文本格式化A(buff,sizeof(buff),A"%s:%s",临时文本_IP.取地址(),临时文本_端口.取地址())
		WsCore.初始化IO()
		WsCore.绑定服务(临时文本_IP,临时文本_端口)
		WsCore.运行_异步()
		文本格式化A(buff,sizeof(buff),A"[开启服务器]监听地址:%s 监听端口:%s",临时文本_IP.取地址(),临时文本_端口.取地址())
		输出日志(buff)
	函数 WS_关闭服务器()
		//正确的关闭方法应该是遍历所有连接并关闭,当所有连接关闭之后即可调用stop(小声bb:当然你不关闭也行,就是没关闭回调就是了)
		WS_断开所有连接()
		WsCore.停止()
		输出日志(A"关闭WS服务器")
	////-----------------------
	函数 WS_加入客户(WS连接* 会话指针)
		WS连接标志 标志=会话指针->取连接标志()
		如果 缓存池.空值() == 缓存池.查找(标志)
			连接信息缓存* 临时缓存 = new 连接信息缓存
			临时缓存->IP地址=会话指针->取客户端IP()
			缓存池[标志] = 临时缓存
			整型 索引 = _连接列表.添加行文本(文本_数值到文本((长整型)标志))
			_连接列表.置项文本(索引, 1, A2W(临时缓存->IP地址))
		否则
			整型 索引 = 搜索客户索引(&_连接列表,会话指针)
			缓存池[标志]->IP地址 = 会话指针->取客户端IP()
			_连接列表.置项文本(索引, 1, A2W(缓存池[标志]->IP地址))
		元素_重绘(_连接列表._句柄, 真)
	函数 WS_通知所有人更新列表()
		cJSON类 回复体
		回复体.置文本(A"type",A"更新在线列表")
		整型 i=0
		变量循环 迭代器 iter = 缓存池.第一个();iter != 缓存池.空值();iter++
			连接信息缓存*查找对象=iter.值
			单字符型 路径[100]={0}
			文本格式化A(路径,100,A"list[%d].name",i)
			回复体.置文本(路径, 查找对象->用户名.取地址())
			i++
		//调试输出A(回复体.取Json文本())
		WS_批量分发消息(回复体.取Json文本())
	函数 WS_批量分发消息(单文本型 消息内容, WS连接* 排除指针=NULL)
		单字符型 buff[255]={0}
		输出日志(A"[推送服务]群发消息")
		变量循环 迭代器 iter = 缓存池.第一个();iter != 缓存池.空值();iter++
			如果 排除指针
				如果 (长整型)iter.键==(长整型)排除指针->取连接标志()
					到循环尾
			文本格式化A(buff, sizeof(buff), A"[回复消息][%lld]%s", (长整型)iter.键, 消息内容.取地址())
			输出日志(buff)
			WsCore.发送文本A(iter.键, 编码_GBK转Utf8(消息内容).取地址())
	////-----------------------
	函数 WS_断开所有连接()
		变量循环 迭代器 iter = 缓存池.第一个();iter != 缓存池.空值();iter++
			WsCore.断开连接(iter.键)
			delete iter.值
		_连接列表.删除行全部()
		缓存池.清空()
		元素_重绘(_连接列表._句柄, 真)
	函数 WS_断开连接(WS连接* 会话指针)
		迭代器 连接 = 缓存池.查找(会话指针->取连接标志())
		如果 连接 == 缓存池.空值()
			返回
		会话指针->关闭连接()
		delete 连接.值
		整型 num = 搜索客户索引(&_连接列表, 会话指针)
		如果 num >- 1
			_连接列表.删除行(num)
		缓存池.删除(连接.键)
		元素_重绘(_连接列表._句柄, 真)
	函数 整型 外部接口_断开连接(整型 nID, 逻辑型* pBool)
		如果 nID == 菜单操作类型_断开连接
			整型 index = _连接列表.取选择行()
			长整型 客户标志_临时 = 索引取客户标志(&_连接列表, index)
			如果 客户标志_临时
				WsCore.断开连接((WS连接标志)客户标志_临时, WS退出代码_正常关闭, A"Bye")
				_连接列表.删除行(index)
				元素_重绘(_连接列表._句柄, 真)
		返回 0
	//---------------
	函数 消息事件_分发消息(WS连接* 会话指针, 连接信息缓存* 用户信息, cJSON类& json)
		逻辑型 登陆中断=假
		单文本型 请求类型 = json.取文本(A"type")
		逻辑型 新用户=假
		如果 请求类型 == A"登陆"
			新用户=真
			登陆中断 = 消息事件_登陆(会话指针, 用户信息, json)
		如果 登陆中断
			返回
		如果 ! 用户信息->连接许可
			//你被Ban了(笑
			单字符型 buff[250] = {0}
			会话指针->发送文本A(A"Auth Error")
			文本格式化A(buff, sizeof(buff), A"[Auth][IP:%s 标志:%lld]未授权访问,强制断开连接.", 会话指针->取客户端IP().取地址(), (长整型)会话指针->取连接标志())
			输出日志(buff)
			WS_断开连接(会话指针)
			返回
		如果 请求类型==A"更新在线列表"
			消息事件_更新在线列表(会话指针, 用户信息, json)
		否则 如果 请求类型 == A"msg"
			消息事件_收到消息(会话指针, 用户信息, json)

		

	函数 逻辑型 消息事件_登陆(WS连接* 会话指针, 连接信息缓存* 用户信息, cJSON类& json)
		单文本型 注册名称 = json.取文本(A"name")
		如果 用户是否存在(注册名称)
			返回 真
		用户信息->用户名=注册名称
		用户信息->连接许可 = 真
		WS_通知所有人更新列表()
		返回 假
	函数 消息事件_更新在线列表(WS连接* 会话指针, 连接信息缓存* 用户信息, cJSON类& json)
		cJSON类 回复体
		回复体.置文本(A"type",A"更新在线列表")
		整型 i=0
		变量循环 迭代器 iter = 缓存池.第一个();iter != 缓存池.空值();iter++
			连接信息缓存*查找对象=iter.值
			单字符型 路径[100]={0}
			文本格式化A(路径,100,A"list[%d].name",i)
			回复体.置文本(路径, 查找对象->用户名.取地址())
			i++
		调试输出(回复体.取Json文本())
		会话指针->发送文本A(编码_GBK转Utf8(回复体.取Json文本()))
	函数 消息事件_收到消息(WS连接* 会话指针, 连接信息缓存* 用户信息, cJSON类& json)
		json.置文本(A"name",用户信息->用户名)
		WS_批量分发消息(json.取Json文本(),会话指针)
		



函数 整型 入口函数_窗口()
	炫彩_初始化(TRUE)
	炫彩_加载资源文件("resource.res")

	我的主窗口.运行()

	炫彩_运行()
	炫彩_退出()
	返回 0

函数 整型 搜索客户索引(列表类* 列表, WS连接* 会话指针)
	长整型 搜索指针 = (长整型)(会话指针->取连接标志())
	整型 num = 列表->取行数量AD()
	整型 索引=-1
	计次循环 整型 i = 0; num
		文本型 当前指针=列表->取项文本(0, 0)
		如果 文本_数值到文本(搜索指针) == 当前指针
			索引 = i
			跳出
	返回 索引

函数 长整型 索引取客户标志(列表类* 列表, 整型 索引)
	如果 索引 < 0
		返回 空
	整型 num = 列表->取行数量AD()
	如果 索引 > num - 1
		返回 空
	常量 字符型* text=列表->取项文本(0,索引)
	返回 文本_文本到双长整型(text)

函数 连接信息缓存* 取连接缓存(WS连接* 会话指针)
	连接信息缓存* 返回值 = 空
	WS连接标志 搜索标志 = 会话指针->取连接标志()
	变量循环 迭代器 iter = 缓存池.第一个();iter != 缓存池.空值();iter++
		如果 搜索标志 == iter.键
			返回值 = iter.值
			跳出
	返回 返回值

函数 逻辑型c 用户是否存在(单文本型& 用户名)
	逻辑型c 返回值 = 假
	变量循环 迭代器 iter = 缓存池.第一个();iter != 缓存池.空值();iter++
		连接信息缓存* 搜索标志 = iter.值
		如果 搜索标志->用户名 == 用户名
			返回值 = 真
			跳出
	返回 返回值